package com.sunwayhorizo.health.business.clinic.orders.basedef;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.ejb.Stateless;

import org.jboss.seam.Component;
import org.jboss.seam.annotations.Name;

import com.sunwayhorizo.health.business.base.BaseManager;
import com.sunwayhorizo.health.business.clinic.orders.query.OrdersQuery;
import com.sunwayhorizo.health.business.clinic.orders.query.OrdersQueryLocal;
import com.sunwayhorizo.health.business.dto.PageDTO;
import com.sunwayhorizo.health.business.dto.ResultsDTO;
import com.sunwayhorizo.health.business.dto.econ.InvoiceElementDTO;
import com.sunwayhorizo.health.business.dto.pham.ContainerDTO;
import com.sunwayhorizo.health.common.DataTypeUtil;
import com.sunwayhorizo.health.common.DateUtil;
import com.sunwayhorizo.health.common.ListUtil;
import com.sunwayhorizo.health.common.StrUtil;
import com.sunwayhorizo.health.hl7.common.Hl7Exception;
import com.sunwayhorizo.health.hl7.datatypes.CE;
import com.sunwayhorizo.health.hl7.datatypes.CS;
import com.sunwayhorizo.health.hl7.datatypes.II;
import com.sunwayhorizo.health.hl7.datatypes.MO;
import com.sunwayhorizo.health.hl7.datatypes.REAL;
import com.sunwayhorizo.health.hl7.datatypes.RTO_MO_PQ;
import com.sunwayhorizo.health.hl7.datatypes.RTO_PQ;
import com.sunwayhorizo.health.hl7.rim.Act;
import com.sunwayhorizo.health.hl7.rim.ActParticipation;
import com.sunwayhorizo.health.hl7.rim.Container;
import com.sunwayhorizo.health.hl7.rim.ControlAct;
import com.sunwayhorizo.health.hl7.rim.InvoiceElement;
import com.sunwayhorizo.health.hl7.rim.Role;
import com.sunwayhorizo.health.hl7.vocabulary.ActIICode;
import com.sunwayhorizo.health.hl7.vocabulary.ActMood;
import com.sunwayhorizo.health.hl7.vocabulary.ActStatus;
import com.sunwayhorizo.health.hl7.vocabulary.EntityCode;
import com.sunwayhorizo.health.hl7.vocabulary.EntityDeterminer;
import com.sunwayhorizo.health.hl7.vocabulary.ParticipationType;
import com.sunwayhorizo.health.hl7.vocabulary.RoleClass;
import com.sunwayhorizo.health.hl7.vocabulary.RoleCode;


/**
 * @ClassName InvoiceElementDefManager <br>
 * @PackageName com.sunwayhorizo.health.business.clinic.orders.basedef <br>
 * @Description 费用明细session bean <br>
 * @Author jinzw <br>
 * @Date 2010-03-07 <br>
 * @Version 1.0 <br>
 * @ModifiedDesc <br>
 * @ModifiedDate <br>
 * @ModifiedBy <br>
 * @Copyright 2010-2020 北京三维海容 All Rights Reserved. <br>
 */

@Name("InvoiceElementDefManager")
@Stateless
public class InvoiceElementDefManager extends BaseManager implements InvoiceElementDefManagerLocal
{
    private OrdersQueryLocal orderQuery = (OrdersQueryLocal)Component.getInstance(OrdersQuery.class);
    @Override
    public ResultsDTO newInvoiceElementDefManager(InvoiceElementDTO invoiceElement) throws Hl7Exception
    {
        if(invoiceElement == null)
        {
            log.info("费用明细信息为空,添加失败");
            return this.getResultsDTO("费用明细信息为空,添加失败", true, null);
        }
        
        //创建费用明细动作并持久化
        InvoiceElement invoiceelement =  newInvoiceElementDet(invoiceElement);
        
        log.info("创建费用明细成功 actid="+invoiceelement.getActId());
        return this.getResultsDTO("创建费用明细成功", true, invoiceelement.getActId());
      
    }
    
    public InvoiceElement newInvoiceElementDet(InvoiceElementDTO invoiceElement) throws Hl7Exception
    {
        if(invoiceElement == null)
        {
            log.info("费用明细信息为空,添加失败");
            return null;
        }
        
        //创建费用明细动作
        CS code = DataTypeUtil.getCS(invoiceElement.getCode());
        InvoiceElement invoiceelement = this.getActFactory().newInvoiceElement(ActMood.DEF, code, null);
      
        //给费用明细赋值
        invoiceelement = converInvoiceElementFormDto(invoiceElement,invoiceelement);
        
        //构建费用明细角色信息
        Role manufacturedProductRole =constructPackageProduct(invoiceElement);
        //药品规格角色参与到药品费用动作中
        if(manufacturedProductRole != null)
        {
            ActParticipation part = getActFactory().newActParticipation();
            part.setTypeCode(ParticipationType.IND);
            addParticipation(manufacturedProductRole, part);
        }
        
        // 创建ControlAct
        ControlAct control = newControlAct(invoiceelement); 
        
        //持久化ControlAct
        save(control);
        log.info("创建费用明细成功 actid="+invoiceelement.getActId());
        return invoiceelement;
    }
    
    @SuppressWarnings("rawtypes")
    @Override
    public ResultsDTO delInvoiceElementDefManager(List ids) throws Hl7Exception
    {
        
        if (ListUtil.isEmpty(ids))
        {
            log.info("删除费用明细失败，数据为空");
            return getResultsDTO("删除费用明细失败，数据为空", false, null);
        }
        for(int i=0; i<ids.size(); i++)
        {
            String id = (String)ids.get(i);
            Act act = baseQuery.findActByActId(Long.valueOf(id));
            int j= delete(act,ParticipationType.IND);
            if(j == 0)
            {
                log.info("删除费用明细成功");
            }
        }
      
        return getResultsDTO("删除费用明细成功", true, null);
        
    }

    @SuppressWarnings("null")
    @Override
    public ResultsDTO updInvoiceElementDefManager(InvoiceElementDTO invoiceElement) throws Hl7Exception
    {
        if(invoiceElement == null && StrUtil.isEmpty(invoiceElement.getActId()))
        {
            log.info("费用信息主键为空，不能修改");
            return this.getResultsDTO("费用信息主键为空，不能修改", false, null);
        }
        //得到费用明细信息
        InvoiceElement invoiceelement = (InvoiceElement) baseQuery.findActByActId(Long.valueOf(invoiceElement.getActId()));
        
        //给费用明细赋值
        invoiceelement = converInvoiceElementFormDto(invoiceElement,invoiceelement);
         
        //修改
        em.merge(invoiceelement);
        
        log.info("费用明细修改成功，费用id为"+invoiceelement.getActId());
        return this.getResultsDTO("费用明细修改成功", true, invoiceelement.getActId());
    }
    
    public int batchUpdInvoiceElement(List<InvoiceElementDTO> invoiceElement) throws Hl7Exception
    {
        int i=0;
        if(ListUtil.isEmpty(invoiceElement)) return i;
        for(InvoiceElementDTO invoiceElementDTO : invoiceElement)
        {
            updInvoiceElementDefManager(invoiceElementDTO);
            i = 1;
        }
        
        return i;
        
    }
    
    @SuppressWarnings("unused")
    public ResultsDTO validationInveId(String id,String actId) throws Hl7Exception
    {
        boolean flag = baseQuery.validateActIIExsit(id, ActIICode.INVOICEELEMENTID.toString(),actId);
        if(true)
        {
            return this.getResultsDTO("该费用编码已经存在", true, "0");
        }
        else
            return this.getResultsDTO("该费用编码已经不存在", true, "1");
    }
    
    @Override
    public ResultsDTO findInvoiceElementDefList(String code,PageDTO pageDTO) throws Hl7Exception
    {
       List<InvoiceElement> inveList = orderQuery.findInvoiceElementByCode(code,pageDTO.getPageNo(),pageDTO.getPageSize());
       if(ListUtil.isNotEmpty(inveList))
       {
           List<InvoiceElementDTO> inveDTOList = new ArrayList<InvoiceElementDTO>();
           for(InvoiceElement inve : inveList)
           {
               InvoiceElementDTO inveDto = converInvoiceElementDTOFormInve(inve);
               inveDTOList.add(inveDto);
           }
           pageDTO.setTotalRecord((int)orderQuery.findInvoiceElementByCode(code));
           return getResultsDTO("费用明细查询成功", true, inveDTOList, pageDTO);
       }
       return getResultsDTO("没有找到相关记录", true, null);
    }
    
    
    //组装费用明细DTO信息
    public InvoiceElementDTO converInvoiceElementDTOFormInve(InvoiceElement inve) throws Hl7Exception
    {
        if(inve == null) return null;
        InvoiceElementDTO invoiceElementDTO = new InvoiceElementDTO();
        invoiceElementDTO.setActId(String.valueOf(inve.getActId()));
        //费用项目编码
        II ii = inve.getId(ActIICode.INVOICEELEMENTID);
        invoiceElementDTO.setId((ii == null || ii.extension() == null) ? "" : ii.extension().toString());
        
        //费用类别
        invoiceElementDTO.setCode((inve.getCode()!= null ? inve.getCode().code().toString() : ""));
        
        //费用状态
        invoiceElementDTO.setStatus((inve.getStatusCode() != null ? inve.getStatusCode().code().toString() : ""));
        
        //费用名称
        invoiceElementDTO.setTitle((inve.getTitle() != null && !inve.getTitle().toString().equals("<Null:NI>") ? inve.getTitle().stringValue() : ""));
        
        //费用说明
        invoiceElementDTO.setText((inve.getText() != null ? inve.getText().stringValue() : ""));
        
        //开始时间
        String startTime = (inve.getEffectiveTime() != null &&  inve.getEffectiveTime().hull() !=null &&  inve.getEffectiveTime().hull().low()!=null ? inve.getEffectiveTime().hull().low().toString() : "");
        invoiceElementDTO.setStartDateTime( DateUtil.formatString(startTime));
        
        //结束时间
        String endTime = (inve.getEffectiveTime() != null && inve.getEffectiveTime().hull() !=null &&  inve.getEffectiveTime().hull().high()!=null ? inve.getEffectiveTime().hull().high().toString() : "");
        invoiceElementDTO.setEndDateTime(DateUtil.formatString(endTime));
        
        //单价
        invoiceElementDTO.setUnitPriceAmt((inve.getUnitPriceAmt() != null && inve.getUnitPriceAmt().numerator() != null && inve.getUnitPriceAmt().numerator().value() != null ? inve.getUnitPriceAmt().numerator().value().stringValue() : ""));
      
        //单位
        invoiceElementDTO.setUnitPriceUnit((inve.getUnitPriceAmt() != null && inve.getUnitPriceAmt().denominator() != null && inve.getUnitPriceAmt().denominator().value() != null ? inve.getUnitPriceAmt().denominator().value().toString() : ""));
        
        //数量
        invoiceElementDTO.setUnitQuantity((inve.getUnitQuantity() != null && inve.getUnitQuantity().numerator() != null && inve.getUnitQuantity().numerator().value() != null ? inve.getUnitQuantity().numerator().value().stringValue() : ""));
        
        //数量单位
        invoiceElementDTO.setUnitQuantityUnit((inve.getUnitQuantity() != null && inve.getUnitQuantity().denominator() != null && inve.getUnitQuantity().denominator().value() != null ? inve.getUnitQuantity().denominator().value().toString() : ""));
       
        //总价
        invoiceElementDTO.setNetAmt((inve.getNetAmt() != null && inve.getNetAmt().value() != null ? inve.getNetAmt().value().stringValue() : ""));
        
        //折扣
        invoiceElementDTO.setFactorNumber((inve.getFactorNumber() == null || inve.getFactorNumber().equals("<Null:NullFlavor: NI>") ? "" : inve.getFactorNumber().stringValue() ));
        
        //加价率
        invoiceElementDTO.setPointsNumber((inve.getPointsNumber() == null || inve.getPointsNumber().equals("<Null:NullFlavor: NI>") ? "" : inve.getPointsNumber() .stringValue()));
        
        //门诊收费分类
        invoiceElementDTO.setOutpRcptFee(getDictionaryFactory().getDictionaryDTOByCe(inve.getIeOutRcptFeeCode()));
        
        //住院收费分类
        invoiceElementDTO.setInpRcptFee(getDictionaryFactory().getDictionaryDTOByCe(inve.getIeInpRcptFeeCode()));
        
        //核算费用分类
        invoiceElementDTO.setTallySubject(getDictionaryFactory().getDictionaryDTOByCe(inve.getIeTallSubjectCode()));
        
        //病案费用分类
        invoiceElementDTO.setMrFeeClass(getDictionaryFactory().getDictionaryDTOByCe(inve.getIeMrFeeClassCode()));
        
        //包装信息
        invoiceElementDTO.setContainer(converContDTOFormContainer((Container)inve.getHl7EntityByAct(ParticipationType.IND, RoleCode.DRUG)));
        
        return invoiceElementDTO;
    }
    
    private InvoiceElement converInvoiceElementFormDto(InvoiceElementDTO invoiceElement,InvoiceElement invoiceelement) throws Hl7Exception
    {
        //收费项目编码
        if(StrUtil.isNotEmpty(invoiceElement.getId()))
        {
            II ii = DataTypeUtil.getII(root, invoiceElement.getId(), ActIICode.INVOICEELEMENTID.toString());
            invoiceelement.setId(ii);
        }
       
        //收费名称
        invoiceelement.setTitle(DataTypeUtil.getST(invoiceElement.getTitle()));
        
        //收费说明
        invoiceelement.setText(DataTypeUtil.getED(invoiceElement.getText()));
        
        //收费项目状态
        invoiceelement.setStatusCode(ActStatus.ACTIVE);
        
        //开始时间
        Date startDate = DateUtil.getDateBy3String(invoiceElement.getStartDateTime());
        //结束时间
        Date endDate = DateUtil.getDateBy3String(invoiceElement.getEndDateTime());
        invoiceelement.setEffectiveTime(DataTypeUtil.getGTS(DataTypeUtil.getIVL_TS(startDate, endDate)));
        
        //单价-单位
        RTO_MO_PQ mopq = DataTypeUtil.getRTO_MO_PQ(invoiceElement.getUnitPriceAmt(), invoiceElement.getUnitPriceUnit());
        invoiceelement.setUnitPriceAmt(mopq);
        
        //数量-数量单位
        RTO_PQ unitQuantity = DataTypeUtil.getRTO_PQ((StrUtil.isNotEmpty(invoiceElement.getUnitQuantity()) ? invoiceElement.getUnitQuantity() : "0"), (StrUtil.isNotEmpty(invoiceElement.getUnitQuantityUnit()) ? invoiceElement.getUnitQuantityUnit() : ""));
        invoiceelement.setUnitQuantity(unitQuantity); 
        
        //总价
        if(StrUtil.isNotEmpty(invoiceElement.getUnitPriceAmt()) && StrUtil.isNotEmpty(invoiceElement.getUnitQuantity()))
        {
            Double netamt = Double.parseDouble(invoiceElement.getUnitPriceAmt())*Double.parseDouble(invoiceElement.getUnitQuantity());
            MO netAmt = DataTypeUtil.getMO(netamt, "元");
            invoiceelement.setNetAmt(netAmt);
        }
      
        //折扣


        
        //加价率
        REAL pointsNumber = DataTypeUtil.getREAL((invoiceElement.getPointsNumber() == null || invoiceElement.getPointsNumber().equals("<Null:NullFlavor: NI>") ? null : invoiceElement.getPointsNumber()));
        invoiceelement.setPointsNumber(pointsNumber);
        
        //门诊收费分类
        CE outpRcptFee = getDictionaryFactory().getCeByDictionaryDTO(invoiceElement.getOutpRcptFee());
        invoiceelement.setIeOutRcptFeeCode(outpRcptFee);
        
        //住院收费分类
        CE inpRcptFee = getDictionaryFactory().getCeByDictionaryDTO(invoiceElement.getInpRcptFee());
        invoiceelement.setIeInpRcptFeeCode(inpRcptFee);
        
        //核算费用分类
        CE tallySubject  = getDictionaryFactory().getCeByDictionaryDTO(invoiceElement.getTallySubject());
        invoiceelement.setIeTallSubjectCode(tallySubject);
        
        //病案费用分类
        CE mrFeeClass   = getDictionaryFactory().getCeByDictionaryDTO(invoiceElement.getMrFeeClass());
        invoiceelement.setIeMrFeeClassCode(mrFeeClass);
        
        return invoiceelement;
    }
    

    //构建药品规格信息
    private Role  constructPackageProduct(InvoiceElementDTO invoiceElement) throws Hl7Exception
    {
        if(invoiceElement.getContainer() == null)  return null;
        
                //创建一个药品包装实体
                CE ce = DataTypeUtil.getCE(EntityCode.PACKAGE.toString());
                Container container = this.getEntityFactory().newContainer(ce, EntityDeterminer.KIND, null);
                
                //给药品规格信息赋值
                container = converContainerToDto(container,invoiceElement.getContainer());
                
                //创建一个药品规格角色
                CE ce1 = DataTypeUtil.getCE(RoleCode.DRUG.toString());
                Role manufacturedProduct = this.getRoleFactory().newRole(RoleClass.MANU, ce1, container, container);
                
                return manufacturedProduct;
    }
    
    //给药品包装规格信息赋值
    private Container converContainerToDto(Container container,ContainerDTO containerDTO) throws Hl7Exception
    {
        //包装规格
        container.setLotNumberText(DataTypeUtil.getST(containerDTO.getPackageSpec()));
        //包装数量-单位
        container.setCapacityQuantity(DataTypeUtil.getPQ(containerDTO.getPackageQuautity(), containerDTO.getPackageUnit()));

        //厂家
        container.setManufcturerCode(DataTypeUtil.getCE(containerDTO.getManufacturer()));
        //包装说明
        container.setDesc(DataTypeUtil.getED(containerDTO.getDesc()));
        //国产、进口、自制
        container.setMadeBY(DataTypeUtil.getCE(containerDTO.getMadeBy()));
        //药品条码
        container.setBarCode(DataTypeUtil.getST(containerDTO.getBarCode()));
        //批准文号
        container.setApprovalFlag(DataTypeUtil.getST(containerDTO.getApprovalNumbe()));
        //贵重标志
        container.setValuableFlag(DataTypeUtil.getST(containerDTO.getValuableFlag()));
        //招标标志
        container.setBidFlag(DataTypeUtil.getST(containerDTO.getBidFlag()));
        //GMP标志
        container.setGmpFlag(DataTypeUtil.getST(containerDTO.getGmpFlag()));
        
        return container;

    }
    
    private ContainerDTO converContDTOFormContainer(Container container) throws Hl7Exception
    {
        if(container == null) return null;
        ContainerDTO containerDTO = new ContainerDTO();
        
        //包装规格
        containerDTO.setPackageSpec((container.getLotNumberText().toString().equals("<Null:NI>") ? "" : container.getLotNumberText().toString()));
        //包装数量-单位
        if(container.getCapacityQuantity() != null && container.getCapacityQuantity().value() != null)
        {
            containerDTO.setPackageQuautity(container.getCapacityQuantity().value().literal().toString());
            containerDTO.setPackageUnit((container.getCapacityQuantity().unit().literal().toString().equals("<Null:NullFlavor: NI>") ? "" : container.getCapacityQuantity().unit().literal().toString()));
        }
        //厂家
        containerDTO.setManufacturer((container.getManufcturerCode() != null && !container.getManufcturerCode().code().toString().equals("<Null:NullFlavor: NI>") ? container.getManufcturerCode().code().toString() : ""));
        //包装说明
        containerDTO.setDesc((container.getDesc() != null ? container.getDesc().stringValue() : ""));
        //国产、进口、自制
        containerDTO.setMadeBy((container.getMadeBY() != null ? container.getMadeBY().code().toString() : ""));
        //药品条码
        containerDTO.setBarCode(container.getBarCode().stringValue());
        //批准文号
        containerDTO.setApprovalNumbe(container.getApprovalFlag().stringValue());
        //贵重标志
        containerDTO.setValuableFlag(container.getValuableFlag().stringValue());
        //招标标志
        containerDTO.setBidFlag(container.getBidFlag().stringValue());
        //GMP标志
        containerDTO.setGmpFlag((container.getGmpFlag().toString().equals("<Null:NI>") ? "" : container.getGmpFlag().toString()));
        
        return containerDTO;
    }

  
    

}
